using System;

namespace FixedPointMath
{
    /// <summary>
    /// 任意角度计算出来的结果，与Mathf.Sin或Mathf.Cos的偏差值，在0.0001749098以下
    /// </summary>
    internal static class SinCosLookup
    {
        /// <summary>
        /// 角度精度: 0.01度
        /// </summary>
        private const long Factor = 100L;

        /// <summary>
        /// 浮动范围
        /// </summary>
        private static Number Float = Number.One / Factor / 2;

        private static readonly int s_90MaxIndex
            ;
        private static readonly int s_180MaxIndex;

        static SinCosLookup()
        {
            s_90MaxIndex = SinCosLookupData.s_Table.Length - 1;
            s_180MaxIndex = s_90MaxIndex + s_90MaxIndex;
        }

        /// <summary>
        /// 获取角度对应的sin值
        /// </summary>
        /// <param name="degree"></param>
        /// <returns></returns>
        public static Number SinDegree(Number degree)
        {
            if (degree < Number.Zero)
            {
                do
                {
                    degree += Number.N360;
                }
                while (degree < Number.Zero);
            }
            else if (degree > Number.N360)
            {
                do
                {
                    degree -= Number.N360;
                }
                while (degree > Number.N360);
            }

            degree += Float;

            degree.value *= Factor;
            if (degree > Number.N18000)
            {
                degree -= Number.N18000;

                var index = degree.AsInt();
                if (index > s_90MaxIndex)
                {
                    index = s_180MaxIndex - index;
                }
                return new Number { value = -SinCosLookupData.s_Table[index] };
            }
            else
            {
                var index = degree.AsInt();
                if (index > s_90MaxIndex)
                {
                    index = s_180MaxIndex - index;
                }
                return new Number { value = SinCosLookupData.s_Table[index] };
            }
        }

        /// <summary>
        /// 获取弧度对于的sin值
        /// </summary>
        /// <param name="radin"></param>
        /// <returns></returns>
        public static Number SinRadin(Number radin)
        {
            return SinDegree(radin * Number.R180 / Number.PI);
        }

        /// <summary>
        /// 获取角度对应的cos值
        /// </summary>
        /// <param name="degree"></param>
        /// <returns></returns>
        public static Number CosDegree(Number degree)
        {
            return SinDegree(degree + Number.N90);
        }

        /// <summary>
        /// 获取弧度对应的cos值
        /// </summary>
        /// <param name="radin"></param>
        /// <returns></returns>
        public static Number CosRadin(Number radin)
        {
            return SinDegree((radin + Number.HalfPI) * Number.R180 / Number.PI);
        }
    }
}
